import {
  ChangeDetectorRef,
  Component,
  EventEmitter,
  Input,
  OnChanges,
  OnInit,
  Output,
  SimpleChanges,
  TemplateRef,
} from '@angular/core';
import { ApesNoAnimationDirective, FunctionProp, InputBoolean, toBoolean, valueFunctionProp } from '@shared/apes/core';
import { ApesI18nService, DateHelperService } from '@shared/apes/i18n';


import { CandyDate } from './lib/candy-date/candy-date';
import { AbstractPickerComponent, CompatibleDate } from './abstract-picker.component';
import { DisabledTimeFn, PanelMode, PresetRanges } from './standard-types';

@Component({
  template: `` // Just for rollup
})

export class DateRangePickerComponent extends AbstractPickerComponent implements OnInit, OnChanges {
  showWeek: boolean = false; // Should show as week picker

  @Input() apesDateRender: FunctionProp<TemplateRef<Date> | string>;
  @Input() apesDisabledTime: DisabledTimeFn;
  @Input() apesRenderExtraFooter: FunctionProp<TemplateRef<void> | string>;
  @Input() @InputBoolean() apesShowToday: boolean = true;
  @Input() apesMode: PanelMode | PanelMode[];
  @Input() apesRanges: PresetRanges;
  @Output() apesOnPanelChange = new EventEmitter<PanelMode | PanelMode[]>();
  @Output() readonly apesOnCalendarChange = new EventEmitter<Date[]>();
  @Output() readonly apesOnOk = new EventEmitter<CompatibleDate>();

  private _showTime: object | boolean;
  @Input() get apesShowTime(): object | boolean {
    return this._showTime;
  }
  set apesShowTime(value: object | boolean) {
    this._showTime = typeof value === 'object' ? value : toBoolean(value);
  }

  get realShowToday(): boolean { // Range not support apesShowToday currently
    return !this.isRange && this.apesShowToday;
  }
  pickerStyle: object; // Final picker style that contains width fix corrections etc.
  extraFooter: TemplateRef<void> | string;

  constructor(i18n: ApesI18nService,
              cdr: ChangeDetectorRef,
              dateHelper: DateHelperService,
              noAnimation?: ApesNoAnimationDirective) {
    super(i18n, cdr, dateHelper, noAnimation);
  }

  ngOnInit(): void {
    super.ngOnInit();

    // Default format when it's empty
    if (!this.apesFormat) {
      if (this.showWeek) {
        this.apesFormat = this.dateHelper.relyOnDatePipe ? 'yyyy-ww' : 'YYYY-WW'; // Format for week
      } else {
        if (this.dateHelper.relyOnDatePipe) {
          this.apesFormat = this.apesFormat ? 'yyyy-MM-dd HH:mm:ss' : 'yyyy-MM-dd';
        } else {
          this.apesFormat = this.apesFormat ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD';
        }
      }
    }
  }

  ngOnChanges(changes: SimpleChanges): void {
    super.ngOnChanges(changes);

    if (changes.apesRenderExtraFooter) {
      this.extraFooter = valueFunctionProp(this.apesRenderExtraFooter);
    }
    if (changes.apesShowTime || changes.apesStyle) {
      this.setFixedPickerStyle();
    }
  }

  // If has no timepicker and the user select a date by date panel, then close picker
  onValueChange(value: CandyDate): void {
    super.onValueChange(value);

    if (!this.apesShowTime) {
      this.closeOverlay();
    }
  }
  onCalendarChange(value: CandyDate[]): void {
    if (this.isRange) {
      const rangeValue = value.map(x => x.getNativeDate());
      this.apesOnCalendarChange.emit(rangeValue);
    }
  }
  // Emitted when done with date selecting
  onResultOk(): void {
    if (this.isRange) {
      if ((this.apesValue as CandyDate[]).length) {
        this.apesOnOk.emit([ this.apesValue[ 0 ].getNativeDate(), this.apesValue[ 1 ].getNativeDate() ]);
      } else {
        this.apesOnOk.emit([]);
      }
    } else {
      if (this.apesValue) {
        this.apesOnOk.emit((this.apesValue as CandyDate).getNativeDate());
      } else {
        this.apesOnOk.emit(null);
      }
    }
    this.closeOverlay();
  }

  onOpenChange(open: boolean): void {
    this.apesOnOpenChange.emit(open);
  }
  private setFixedPickerStyle(): void {
    const showTimeFixes: { width?: string } = {};
    if (this.apesShowTime) {
      showTimeFixes.width = this.isRange ? '350px' : '195px';
    }
     this.pickerStyle = { ...showTimeFixes, ...this.apesStyle };
   }
}
